mod behavior;
mod command;
mod swarm;
mod kadevents;

#[macro_use]
extern crate tracing;

use libp2p::{identity::Keypair, Multiaddr, PeerId};
use tauri::{
  async_runtime::{channel, Sender},
  plugin::{Builder, TauriPlugin},
  AppHandle, Manager, Runtime, State, Window,
};

use crate::command::Command;

struct MyState(Sender<Command>);

#[tauri::command]
async fn send_message<R: Runtime>(
  _app: AppHandle<R>,
  _window: Window<R>,
  state: State<'_, MyState>,
  message: &str,
) -> Result<(), ()> {
  let _ = state
    .0
    .send(Command::SendMessage {
      message: message.to_owned(),
    })
    .await;
  Ok(())
}

#[tauri::command]
async fn subscribe<R: Runtime>(
  _app: AppHandle<R>,
  _window: Window<R>,
  state: State<'_, MyState>,
  topic: &str,
) -> Result<(), ()> {
  let _ = state
    .0
    .send(Command::Subscribe {
      topic: topic.to_owned(),
    })
    .await;
  Ok(())
}

#[tauri::command]
async fn unsubscribe<R: Runtime>(
  _app: AppHandle<R>,
  _window: Window<R>,
  state: State<'_, MyState>,
  topic: &str,
) -> Result<(), ()> {
  let _ = state
    .0
    .send(Command::Unsubscribe {
      topic: topic.to_owned(),
    })
    .await;
  Ok(())
}

/// Initializes the plugin.
pub fn init<R: Runtime>() -> TauriPlugin<R> {
  Builder::new("libp2p-signal")
    .invoke_handler(tauri::generate_handler![
      send_message,
      subscribe,
      unsubscribe
    ])
    .on_webview_ready(|window| {
      let (tx, rx) = channel(10);
      window.manage(MyState(tx));
      tauri::async_runtime::spawn(async move {
        let _ = swarm::run_swarm(window, rx).await.unwrap();
      });
    })
    .build()
}

pub struct SwarmOptions {
  /// The keypair for the PKI based identity of the local node.
  pub keypair: Keypair,
  /// The peer address of the local node created from the keypair.
  pub peer_id: PeerId,
  /// The peers to connect to on startup.
  pub bootstrap: Vec<(PeerId, Multiaddr)>,
}
